#pragma once
#include<iostream>
#include<string>
#include <stdarg.h>
#include<ctime>
#include<unistd.h>
using namespace std;

//封装一个日志

// 错误是分等级的
#define DEBUG 0 // 调试级
#define NORMAL 1 //正常
#define WARNING 2 //简单的警告
#define ERROR 3 // 出错了，但不影响运行
#define FATAL 4 // 出错了，并且是致命的错误，无法继续运行

//变成守护进程后，想看到日志可以将日志写到文件里，这里可以分类一下
#define LOG_NOMRAL "log.normal"
#define LOG_ERROR "log.error"

const char* to_levelstr(int level)
{
    switch(level)
    {
        case DEBUG: return "DEBUG";
        case NORMAL: return "NORMAL";
        case WARNING: return "WARNING";
        case ERROR: return "ERROR";
        case FATAL: return "FATAL";

        default: return nullptr;
    }
}

// 除了日志类型，还有日志的格式
// [日志等级][时间][pid][message]
void logMessage(int level, const char* format, ...)
{
    // 这里为了让日志有自己想要的格式，所以这里要自己弄一下
#define NUM 1024
    char logprefix[NUM];
    snprintf(logprefix, sizeof(logprefix), "[%s][%ld][pid: %d]", to_levelstr(level), (long int)time(nullptr), getpid());
    // (long int)time(nullptr)是获取时间戳

    char logcontent[NUM];
    va_list arg; //表示可变参数列表的起始位置(地址)
    va_start(arg, format); //填format是因为，解析形参的时候是从右到左的，当可变参数列表走到结束的时候，刚好就是format这个参数
    vsnprintf(logcontent, sizeof(logcontent), format, arg);


    // cout << logprefix << ": " << logcontent << endl;

    FILE* log = fopen(LOG_NOMRAL, "a");
    FILE* err = fopen(LOG_ERROR, "a");
    if(log != nullptr && log != nullptr)
    {
        FILE* cur = nullptr;
        if(level == DEBUG || level == NORMAL || level == WARNING)
            cur = log;
        if(level == ERROR || level == FATAL)
            cur = err;

        fprintf(cur, "%s%s\n", logprefix, logcontent);

        fclose(log);
        fclose(err);
    }

}